import { ShopLoginPipe } from './../../../pipe/account/shop-login.pipe';
import { ShopRegisterPipe } from '../../../pipe/account/shop-register.pipe';
import { ResponseInterceptor } from './../../../interceptor/response/response.interceptor';
import { UserService } from './../../../service/user/user.service';
import { getRandomCode } from 'src/util/index';
import { YYYYMMDD } from 'src/util/time';
import { UserTempService } from 'src/service/user-temp/user-temp.service';
import {
    Body,
    Controller,
    Get,
    Post,
    Req,
    Response,
    BadRequestException,
    UseInterceptors,
    UsePipes,
    Res,
    HttpException,
    UnauthorizedException,
} from '@nestjs/common';
import config from 'src/config/config';
import { ToolsService } from 'src/service/tools/tools.service';
import * as md5 from 'md5';
import * as joi from 'joi';
import * as jwt from 'jsonwebtoken';
import * as bcrypt from 'bcrypt';
import { GoodResponse } from 'src/util/response';

const registerSchema: joi.ObjectSchema = joi.object().keys({
    email: joi.string().pattern(config.emailPattern).required(),
    password: joi.string().pattern(config.shopUserPasswordPattern).required(),
    password_repeat: joi.ref('password'),
    code: joi
        .string()
        .pattern(/^[0-9]{6}$/)
        .required(),
});
const loginSchema: joi.ObjectSchema = joi.object().keys({
    email: joi.string().pattern(config.emailPattern),
    phone: joi.string().pattern(config.phonePattern),
    password: joi.string().pattern(config.shopUserPasswordPattern).required(),
});
@UseInterceptors(ResponseInterceptor)
@Controller(`${config.shopApiPath}/user`)
export class UserController {
    constructor(
        private readonly toolsService: ToolsService,
        private readonly userTempService: UserTempService,
        private readonly userService: UserService,
    ) {}
    @Get('captcha')
    index(@Req() req, @Res() res) {
        const currentCapture = this.toolsService.captcha();
        //session存图形验证码的答案文字
        console.log({ shop图形验证码: currentCapture.text });
        req.session.captchaText = currentCapture.text;
        res.type('image/svg+xml');
        res.send(currentCapture.data);
    }
    @Post('mailCode')
    async sendMailCode(@Body() body, @Req() req) {
        const { lastSendMailCodeTime } = req.session;
        if (lastSendMailCodeTime && Date.now() - lastSendMailCodeTime < 1000 * 60) {
            throw new BadRequestException('验证码发送间隔要大于一分钟');
        }
        const { email, captcha } = body;
        if (!captcha) throw new BadRequestException('请输入验证码');
        if (!captcha.toLowerCase() || captcha !== (req.session.captchaText || '').toLowerCase())
            throw new BadRequestException('验证码错误');
        if (!email || !config.emailPattern.test(email)) throw new BadRequestException('邮箱不符合格式');
        const ip = req.ip.replace(/::ffff:/, '');
        const sign = md5(`${email}${YYYYMMDD()}`);
        const tempResult = await this.userTempService.find({ sign });
        if (tempResult?.length) {
            const { _id, send_count } = tempResult[0];
            if (send_count >= config.emialCodeLimit) throw new BadRequestException('发送次数已达上限');
            await this.userTempService.update({ _id, send_count: send_count + 1 });
        } else {
            await this.userTempService.create({ sign, send_count: 1, ip, email });
        }
        const randomCode = getRandomCode();
        //session存随机验证码
        req.session.emailCodeText = randomCode;
        try {
            await this.toolsService.sendMailCode({ to: email, type: '注册账号', code: randomCode });
            req.session.lastSendMailCodeTime = Date.now();
            return '验证码已发送';
        } catch (error) {
            return '发送失败';
        }
    }
    @Post('checkEmail')
    async checkEmail(@Body() body) {
        const { email } = body;
        const result = await this.userService.find({ email });
        if (result?.length) throw new BadRequestException('用户已存在');
        return;
    }
    @Post('register')
    @UsePipes(new ShopRegisterPipe(registerSchema))
    async register(@Body() body, @Req() req, @Res() res) {
        const { email, code, password } = body;
        const userResult = await this.userService.find({ email });
        if (userResult?.length) throw new BadRequestException('用户已存在');
        if (code !== req.session.emailCodeText) throw new BadRequestException('验证码错误');
        const ip = req.ip.replace(/::ffff:/, '');
        const user = await this.userService.create({ email, last_ip: ip, status: 1, password });
        const token = jwt.sign({ _id: user._id }, config.jwtSecret);
        res.cookie(config.authCookieKey, token, config.cookie);
        req.session.userInfo = user;
        res.send(GoodResponse(token));
    }
    @Post('login')
    @UsePipes(new ShopLoginPipe(loginSchema))
    async login(@Body() body, @Res() res, @Req() req) {
        const { email, phone, password } = body;
        if (!email && !phone) throw new BadRequestException('请输入账号');
        let user = null;
        const project = { email: 1, phone: 1, password: 1 };
        if (email) {
            user = await this.userService.find({ email }, project);
        } else if (phone) {
            user = await this.userService.find({ phone }, project);
        }
        if (!user?.length) throw new BadRequestException('用户不存在');
        const passwordIsRight = bcrypt.compareSync(password, user[0].password);
        if (!passwordIsRight) throw new HttpException('密码错误', 400);
        const token = jwt.sign({ _id: user[0]._id }, config.jwtSecret);
        res.cookie(config.authCookieKey, token, config.cookie);
        req.session.userInfo = user[0];
        res.send(GoodResponse(token));
    }

    @Get()
    async getUserForRoute(@Req() req) {
        return await this.userService.getUser(req);
    }
    @Post('logout')
    async logout(@Res() res, @Req() req) {
        res.clearCookie(config.authCookieKey);
        req.session.userInfo = null;
        res.send(GoodResponse(undefined, '退出登录成功'));
    }
}
